package com.pkt.item.service;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.item.piketao.bo.SpuBo;
import com.item.piketao.dao.*;
import com.piketao.common.pojo.PageInfo;
import com.pkt.item.mapper.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author: xinglongge
 * @Date: 2020/3/4 19 06
 * @Description:
 */
@Service
public class GoodsService {
    private final SpuDetailMapper spuDetailMapper;
    private final SpuMapper spuMapper;
    private final CategoryService categoryService;
    private final BrandMapper brandMapper;
    private final SkuMapper skuMapper;
    private final StockMapper stockMapper;


    @Autowired
    public GoodsService(SpuDetailMapper spuDetailMapper, SpuMapper spuMapper,
                        BrandMapper brandMapper, CategoryService categoryService,
                        SkuMapper skuMapper, StockMapper stockMapper) {
        this.spuDetailMapper = spuDetailMapper;
        this.spuMapper = spuMapper;
        this.brandMapper = brandMapper;
        this.categoryService = categoryService;
        this.skuMapper = skuMapper;
        this.stockMapper = stockMapper;
    }

    /**
     * 分页查询商品列表
     *
     * @param key
     * @param saleable
     * @param page
     * @param rows
     * @return
     */
    public PageInfo<SpuBo> querySpuByPage(String key, Boolean saleable, Integer page, Integer rows) {
        Example example = new Example(Spu.class);
        Example.Criteria criteria = example.createCriteria();
        //添加查询条件
        if (StringUtils.isNotBlank(key)) {
            criteria.andLike("title", "%" + key + "%");
        }
        //添加上下架的过滤条件
        if (saleable != null) {
            criteria.andEqualTo("saleable", saleable);
        }
        //添加分页
        if (rows==-1){
            rows = spuMapper.selectCount(null);
        }
        PageHelper.startPage(page, rows);
        //执行查询，获取spu集合
        Page<Spu> spus = (Page<Spu>) spuMapper.selectByExample(example);
        //spu集合转化成spuBo集合
        List<SpuBo> spuBos = spus.getResult().stream().map(spu -> {
            SpuBo spuBo = new SpuBo();
            BeanUtils.copyProperties(spu, spuBo);
            //查询品牌名称
            Brand brand = brandMapper.selectByPrimaryKey(spu.getBrandId());
            spuBo.setBname(brand.getName());
            //查询分类名称
            List<String> cname = categoryService.queryNameByIds(Arrays.asList(spu.getCid1(), spu.getCid2(), spu.getCid3()));
            spuBo.setCname(StringUtils.join(cname, ">>"));
            return spuBo;
        }).collect(Collectors.toList());
        //返回page对象
        return new PageInfo<>(spus.getTotal(), spus.getPageNum(), spuBos);
    }

    /**
     * 保存商品
     *
     * @param spuBo
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public void saveGoods(SpuBo spuBo) {
        //先新增spu
        spuBo.setId(null);
        spuBo.setSaleable(true);
        spuBo.setValid(true);
        spuBo.setCreateTime(new Date());
        spuBo.setLastUpdateTime(spuBo.getCreateTime());
        spuMapper.insertSelective(spuBo);
        //再去新增spuDetail
        SpuDetail spuDetail = spuBo.getSpuDetail();
        spuDetail.setSpuId(spuBo.getId());
        spuDetailMapper.insertSelective(spuDetail);

        //再去新增sku stock
        saveOrUpdateSkuAndStock(spuBo.getSkus(), spuBo.getId(), null);

    }

    /**
     * 查询SpuDetail通过spuId
     * @param id
     * @return
     */
    public SpuDetail querySpuDetailById(Long id) {

        return spuDetailMapper.selectByPrimaryKey(id);
    }

    /**
     *查询sku通过spuId
     * @param spuId
     * @return
     */
    public List<Sku> querySkuBySpuId(Long spuId) {
        // 查询sku
        Sku record = new Sku();
        record.setSpuId(spuId);
        List<Sku> skus = this.skuMapper.select(record);
        for (Sku sku : skus) {
            // 同时查询出库存
            sku.setStock(this.stockMapper.selectByPrimaryKey(sku.getId()).getStock());
        }
        return skus;
    }

    /**
     * 更新商品信息
     *
     * @param spu
     */
    @Transactional(rollbackFor = Exception.class)
    public void update(SpuBo spu) {
        // 查询以前sku
        List<Sku> skus = this.querySkuBySpuId(spu.getId());
        // 如果以前存在，则删除
        Map<String, Date> createTimes = null;
        if (!CollectionUtils.isEmpty(skus)) {
            List<Long> ids = skus.stream().map(Sku::getId).collect(Collectors.toList());
            createTimes = skus.stream().collect(Collectors.toMap(Sku::getIndexes, Sku::getCreateTime));
            // 删除以前库存
            Example example = new Example(Stock.class);
            example.createCriteria().andIn("skuId", ids);
            this.stockMapper.deleteByExample(example);

            // 删除以前的sku
            Sku record = new Sku();
            record.setSpuId(spu.getId());
            this.skuMapper.delete(record);

        }
        // 新增sku和库存
        saveOrUpdateSkuAndStock(spu.getSkus(), spu.getId(), createTimes);

        // 更新spu 三个null防止外部伪装注入
        spu.setCreateTime(null);
        spu.setValid(null);
        spu.setSaleable(null);
        spu.setLastUpdateTime(new Date());
        this.spuMapper.updateByPrimaryKeySelective(spu);

        // 更新spu详情
        this.spuDetailMapper.updateByPrimaryKeySelective(spu.getSpuDetail());
    }

    /**
     * 保存或新增sku
     * @param skus
     * @param id
     * @param createTimes
     */
    private void saveOrUpdateSkuAndStock(List<Sku> skus, Long id, Map<String, Date> createTimes) {
        //再去新增sku stock
        for (Sku sku : skus) {
            sku.setId(null);
            sku.setSpuId(id);
            Date createDate = createTimes.get(sku.getIndexes());
            sku.setCreateTime(createDate == null ? new Date() : createDate);
            sku.setLastUpdateTime(new Date());
            skuMapper.insertSelective(sku);

            Stock stock = new Stock();
            stock.setSkuId(sku.getId());
            stock.setStock(sku.getStock());
            stockMapper.insertSelective(stock);
        }

    }
}
